package com.chuangke.sinopecsms;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Random;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.stream.Collectors;

import org.apache.commons.codec.digest.HmacAlgorithms;
import org.apache.commons.codec.digest.HmacUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;

import cn.hutool.http.HttpBase;
import cn.hutool.http.HttpRequest;

@Service
public class SmsService {

	private static String API_KEY ="50d625d48481ac66189ae867397dfbb6";
	private static String SECRET_KEY = "55766c386733c628fe49c1d5d8571b8e4812bd6ef869e244949a87e038145695";
	public static String TEMPLATE_ID = "1031179178908635136" ;
	
	private static final String DOMAIN = "https://opassapi.infocloud.cc/";
	private static final String MESSAGE_SEND = "message/send";
	private static final String MESSAGE_SEND_BATCH = "message/sendBatch";
	public static final String MESSAGE_ARRIVE_QRY = "sms/arrive/qry";
	
	/**
	 * 短信发送。⽆参短信模板内容发送，即所有⼿机号接收到的短信内容⼀样
	 * 
	 * @param templateCode
	 * @param phones       ⼿机号。⼿机号最⼤个数限制1000
	 * @return
	 */
	public String send(String templateCode, String... phones) throws IOException {
		return send(templateCode, null, phones);
	}

	/**
	 * 短信发送。不同⼿机号对应相同的短信模板变量值，即所有⼿机号接收到的短信内容⼀样
	 * 
	 * @param templateCode
	 * @param params       模板参数变量值
	 * @param phones       ⼿机号。⼿机号最⼤个数限制1000
	 * @return
	 */
	public String send(String templateCode, LinkedList<String> params, String... phones)
			throws IOException {
		//⼿机号先去重，然后再转换
		return sendBatch(templateCode, params != null && !params.isEmpty() ? JSON.toJSONString(params) : null,
				Arrays.stream(phones).collect(Collectors.toSet()).stream().collect(Collectors.joining(",")), false);
	}

	/**
	 * 短信发送。不同⼿机号对应不同的短信模板变量值，即所有⼿机号接收到的短信内容不⼀ 样
	 * 
	 * @param templateCode    模板ID
	 * @param phonesAndParams ⼿机号-⼿机号对应的模板参数。⼿机号最⼤个数限制500
	 * @return
	 */
	public String send(String templateCode, Map<String, LinkedList<String>> phonesAndParams)
			throws IOException {
		return sendBatch(templateCode, JSON.toJSONString(phonesAndParams.values()),
				JSON.toJSONString(phonesAndParams.keySet()), true);
	}

	/**
	 * 短信发送
	 * 
	 * @param templateCode 模板ID
	 * @param paramsJson   模板参数
	 * @param phonesJson   ⼿机号
	 * @param batch        true：使⽤MESSAGE_SEND_BATCH接⼝发送；false:使⽤ MESSAGE_SEND接⼝发送
	 * @return HttpResponse
	 * @throws IOException
	 */
	private String sendBatch(String templateCode, String paramsJson, String phonesJson, boolean batch)
			throws IOException {
		if (StringUtils.isAnyEmpty(templateCode,phonesJson)) {
			throw new NullPointerException("模板id或⼿机号不能为空");
		}
		
		Map<String, String> headers = getHeaders();
		
		Map<String, String> bodyParams = new HashMap<>(4);
		if (batch) {
			if (StringUtils.isAnyEmpty(paramsJson)) {
				throw new NullPointerException("短信发送所有⼿机号接收到的短信内容不⼀样时，模板参数值不能为空");
			}
			bodyParams.put("phonesJson", phonesJson);
			//模板变量内容
			bodyParams.put("templateParamJson", paramsJson);
		} else {
			bodyParams.put("phones", phonesJson);
			//模板变量内容
			if (StringUtils.isNotEmpty(paramsJson)) {
				bodyParams.put("templateParam", paramsJson);
			}
		}
		
		bodyParams.put("templateCode", templateCode);
		
		//排序
		SortedMap<String, String> sortedMap = new TreeMap<>(bodyParams);
		headers.forEach((k, v) -> sortedMap.put(k, v));
		
		//⽣成签名
		headers.put("x-sign", getSignature(SECRET_KEY, sortedMap, HmacAlgorithms.HMAC_SHA_224));
		
		String url = DOMAIN + (batch ? MESSAGE_SEND_BATCH : MESSAGE_SEND) ;
		
		String reponseBody = HttpRequest.post(url).httpVersion(HttpBase.HTTP_1_1).body(JSON.toJSONString(bodyParams))
				.timeout(1000).addHeaders(headers).execute().body() ;
		
		return reponseBody ;
	}

	private Map<String, String> getHeaders() {
		Map<String, String> headers = new HashMap<>();
		headers.put("x-api-key", API_KEY);
		headers.put("x-sign-method", HmacAlgorithms.HMAC_SHA_224.getName());
		headers.put("x-nonce", getRandomNickname(10));
		headers.put("x-timestamp", String.valueOf(System.currentTimeMillis()));
		return headers;
	}

	/**
	 * 签名⽣成
	 * 
	 * @param secret
	 * @param sortedMap
	 * @param hmacAlgorithms
	 * @return
	 */
	private String getSignature(String secret, SortedMap<String, String> sortedMap,
			HmacAlgorithms hmacAlgorithms) {
		// 将参数拼接为字符串
		// e.g. "key1=value1&key2=value2"
		StringBuffer plainText = new StringBuffer();
		for (Map.Entry<String, String> entry : sortedMap.entrySet()) {
			plainText.append(entry.getKey() + "=" + entry.getValue());
			plainText.append("&");
		}
		if (StringUtils.isNotEmpty(plainText)) {
			plainText.deleteCharAt(plainText.length() - 1);
		}
		return new HmacUtils(hmacAlgorithms, secret).hmacHex(plainText.toString());
	}

	/**
	 * 随机数⽣成
	 * 
	 * @param length
	 * @return
	 */
	private String getRandomNickname(int length) {
		String val = "";
		Random random = new Random();
		for (int i = 0; i < length; i++) {
			// 输出字⺟还是数字
			String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
			// 字符串
			if ("char".equalsIgnoreCase(charOrNum)) {
				// 取得⼤写字⺟还是⼩写字⺟
				int choice = random.nextInt(2) % 2 == 0 ? 65 : 97;
				val += (char) (choice + random.nextInt(26));
			} else if ("num".equalsIgnoreCase(charOrNum)) { // 数字
				val += String.valueOf(random.nextInt(10));
			}
		}
		return val;
	}
	
//	/**
//	 * 回执信息查询只能查询最近6⼩时内的回执信息, 返回过的数据不会再次返回, 建议查询 频次1分钟，接⼝单次查询最⼤返回的回执条数为600
//	 * 
//	 * @param msgids 短信发送msgid
//	 * @return 除DELIVRD外，其他都是未送达
//	 */
//	public static String getArriveByIds(String... msgids) throws IOException {
//		if (msgids == null) {
//			throw new NullPointerException("msgid不能为空");
//		}
//		Map<String, Object> headers = getHeaders();
//		Map<String, Object> bodyParams = new HashMap<>(4);
//		bodyParams.put("msgId",
//				Arrays.stream(msgids).collect(Collectors.toSet()).stream().collect(Collectors.joining(",")));
//		//排序
//		SortedMap<String, Object> sortedMap = new TreeMap<>(bodyParams);
//		headers.forEach((k, v) -> sortedMap.put(k, v));
//		//⽣成签名
//		headers.put("x-sign", getSignature(SECRET_KEY, sortedMap, HmacAlgorithms.HMAC_SHA_224));
//		Request request = Request.Post(DOMAIN + MESSAGE_ARRIVE_QRY).version(HttpVersion.HTTP_1_1)
//				//设置连接超时
//				.connectTimeout(1000)
//				//设置⽂本读取超时
//				.socketTimeout(1000);
//		headers.forEach((k, v) -> request.addHeader(k, String.valueOf(v)));
//		return request.bodyString(JSON.toJSONString(bodyParams), ContentType.APPLICATION_JSON).execute()
//				.returnResponse();
//	}
}
